﻿using LdtJudge.DataEngine.Model.XMLConfigModel.DataStores;
using LdtJudge.DataEngine.Model.XMLConfigModel.SameNodeConfigModel;
using System;
using System.Collections.Generic;
using System.Linq;

namespace LdtDataEngin.ModuleDetail.OptimizationModule.EvidenceDerivation
{
    /// <summary>
    /// 获取证据对应关系实体
    /// </summary>
    public class MultFactUnionDataModel
    {
        /// <summary>
        /// 对数据实体进行比对
        /// </summary>
        /// <param name="dataModelListOne">第一份实体</param>
        /// <param name="oneParentID">第一实体父级ID</param>
        /// <param name="dataModelListTowe">第二份实体</param>
        /// <param name="oneParentID">第二实体父级ID</param>
        /// <param name="xmlConfigModels">配置实体</param>
        /// <param name="resultnode">结果集</param>
        /// <param name="nodeHandleType">对比方式</param>
        public void MultiFactUnionNode(List<DataModel> dataModelListOne, string oneParentID, List<DataModel> dataModelListTowe, string toweParentID, List<SameNodeXml> xmlConfigModels, List<RelationShip> resultnode, string nodeHandleType)
        {
            if (dataModelListOne.FirstOrDefault(a => a.ParentId == oneParentID) != null && dataModelListTowe.FirstOrDefault(a => a.ParentId == toweParentID) != null)
            {
                foreach (DataModel dataModelone in dataModelListOne.Where(a => a.ParentId == oneParentID))
                {
                    string xmlpath = dataModelone.XmlPath;
                    string configxmlpath = xmlpath;
                    if (!string.IsNullOrEmpty(xmlpath))
                    {
                        if (xmlpath.Substring(0, 1) == @"/")
                        {
                            configxmlpath = xmlpath.Substring(1, xmlpath.Length - 1);
                        }
                        else
                        {
                            xmlpath = @"/" + xmlpath;
                        }
                    }
                    SameNodeXml optimizeSameNodeXML = xmlConfigModels?.FirstOrDefault(a => a.XmlPath == configxmlpath); 
                    if (dataModelListTowe.FirstOrDefault(a => a.XmlPath == xmlpath || a.XmlPath == configxmlpath) != null)
                    {
                        List<DataModel> dataModelListTow = dataModelListTowe.Where(a => a.XmlPath == dataModelone.XmlPath || a.XmlPath == configxmlpath).ToList();
                        foreach (DataModel dataTowe in dataModelListTow)
                        {
                            if (optimizeSameNodeXML != null)
                            {
                                //存在同节点判定
                                List<RelationShip> relationShipList = IsDetermine(dataModelone, dataTowe, optimizeSameNodeXML, "b");
                                if (relationShipList.Count > 0)
                                {
                                    resultnode.AddRange(relationShipList);
                                }
                            }
                            else
                            {
                                foreach (AttributeInfo attributeInfo in dataModelone.AttributesList)
                                {
                                    if (attributeInfo.Name.ToLower()!="id")
                                    {
                                        var attinfoTow = dataTowe.AttributesList.FirstOrDefault(a => a.Name == attributeInfo.Name);
                                        if (attinfoTow!=null)
                                        {
                                            string oneSave = attributeInfo.sourceList.FirstOrDefault(a => a.IsCheck == "1").SaveValue;
                                            string towSave = attinfoTow.sourceList.FirstOrDefault(a => a.IsCheck == "1").SaveValue;
                                            if (oneSave== towSave)
                                            {
                                                RelationShip relationShip = new RelationShip();
                                                relationShip.EvidenID = dataModelone.ID;
                                                relationShip.ElmentID = dataTowe.ID;
                                                relationShip.XmlPath = configxmlpath + "/@" + attinfoTow.Name;
                                                relationShip.Type = "1";
                                                resultnode.Add(relationShip);
                                            }
                                        }
                                    }
                                    
                                }
                            }

                            List<RelationShip> dataModelList = new List<RelationShip>();
                            //不存在同节点判定
                            MultiFactUnionNode(dataModelListOne, dataModelone.ID, dataModelListTowe, dataTowe.ID, xmlConfigModels, dataModelList, "b");
                            if (dataModelList.Count > 0)
                            {
                                resultnode.AddRange(dataModelList);
                                break;
                            }
                        }
                    }
                    else
                    {
                        MultiFactUnionNode(dataModelListOne, dataModelone.ID, dataModelListTowe, toweParentID, xmlConfigModels, resultnode, "b");
                    }
                }
            }
        }

        /// <summary>
        /// 进行数据对比
        /// </summary>
        /// <param name="dataModelOne">第一个数据源</param>
        /// <param name="dataModelTowe">第二个数据源</param>
        /// <param name="optimizeSameNodeXML">配置信息</param>
        /// <returns></returns>
        private List<RelationShip> IsDetermine(DataModel dataModelOne, DataModel dataModelTowe, SameNodeXml optimizeSameNodeXML, string nodeHandleType)
        {
            List<RelationShip> relationShipList = new List<RelationShip>();
            foreach (HandleType handleType in optimizeSameNodeXML.HandleTypes)
            {
                if (handleType.Code.IndexOf(nodeHandleType) > -1)
                {
                    try
                    {
                        CurrentNote currentnoteAttr = handleType.CurrentNote[0];
                        AttributeInfo attributeone = dataModelOne.AttributesList.FirstOrDefault(a => a.Name == currentnoteAttr.Name && a.sourceList.FirstOrDefault(b => b.IsCheck == "1") != null);
                        AttributeInfo attributetow = dataModelTowe.AttributesList.FirstOrDefault(a => a.Name == currentnoteAttr.Name && a.sourceList.FirstOrDefault(b => b.IsCheck == "1") != null);

                        if (attributeone != null && attributetow != null)
                        {
                            if (attributeone.sourceList.FirstOrDefault(a => a.IsCheck == "1").SaveValue == attributetow.sourceList.FirstOrDefault(a => a.IsCheck == "1").SaveValue)
                            {
                                RelationShip relationShipzt = new RelationShip();
                                relationShipzt.EvidenID = dataModelOne.ID;
                                relationShipzt.ElmentID = dataModelTowe.ID;
                                relationShipzt.XmlPath = optimizeSameNodeXML.XmlPath;
                                relationShipzt.Type = "0";
                                relationShipList.Add(relationShipzt);

                                foreach (AttributeInfo attrOne in dataModelOne.AttributesList)
                                {
                                    if (attrOne.Name.ToLower() != "id")
                                    {
                                        AttributeInfo attrTowe = dataModelTowe.AttributesList.FirstOrDefault(a => a.Name == attrOne.Name);
                                        if (attrTowe != null)
                                        {
                                           
                                            if (attrOne.sourceList.FirstOrDefault(a => a.IsCheck == "1").SaveValue == attrTowe.sourceList.FirstOrDefault(a => a.IsCheck == "1").SaveValue)
                                            {
                                                RelationShip relationShip = new RelationShip();
                                                relationShip.EvidenID = dataModelOne.ID;
                                                relationShip.ElmentID = dataModelTowe.ID;
                                                relationShip.XmlPath = optimizeSameNodeXML.XmlPath + "/@" + attrOne.Name;
                                                relationShip.Type = "1";
                                                relationShipList.Add(relationShip);
                                            }
                                            else
                                            {
                                                RelationShip relationShip = new RelationShip();
                                                relationShip.EvidenID = dataModelOne.ID;
                                                relationShip.ElmentID = dataModelTowe.ID;
                                                relationShip.XmlPath = optimizeSameNodeXML.XmlPath + "/@" + attrOne.Name;
                                                relationShip.Type = "2";
                                                relationShipList.Add(relationShip);
                                            }
                                        }
                                        else
                                        {
                                            RelationShip relationShip = new RelationShip();
                                            relationShip.EvidenID = dataModelOne.ID;
                                            relationShip.ElmentID = dataModelTowe.ID;
                                            relationShip.XmlPath = optimizeSameNodeXML.XmlPath + "/@" + attrOne.Name;
                                            relationShip.Type = "2";
                                            relationShipList.Add(relationShip);
                                        }
                                    }
                                }

                                foreach (AttributeInfo attrOne in dataModelTowe.AttributesList)
                                {
                                    if (attrOne.Name.ToLower() != "id"&& relationShipList.FirstOrDefault(a=> a.XmlPath==optimizeSameNodeXML.XmlPath + "/@" + attrOne.Name)==null)
                                    {
                                        AttributeInfo attrTowe = dataModelOne.AttributesList.FirstOrDefault(a => a.Name == attrOne.Name);
                                        if (attrTowe != null)
                                        {
                                            if (attrOne.sourceList.FirstOrDefault(a => a.IsCheck == "1").SaveValue == attrTowe.sourceList.FirstOrDefault(a => a.IsCheck == "1").SaveValue)
                                            {
                                                RelationShip relationShip = new RelationShip();
                                                relationShip.EvidenID = dataModelOne.ID;
                                                relationShip.ElmentID = dataModelTowe.ID;
                                                relationShip.XmlPath = optimizeSameNodeXML.XmlPath + "/@" + attrOne.Name;
                                                relationShip.Type = "1";
                                                if (!relationShipList.Contains(relationShip))
                                                {
                                                    relationShipList.Add(relationShip);
                                                }
                                            }
                                            else
                                            {
                                                RelationShip relationShip = new RelationShip();
                                                relationShip.EvidenID = dataModelOne.ID;
                                                relationShip.ElmentID = dataModelTowe.ID;
                                                relationShip.XmlPath = optimizeSameNodeXML.XmlPath + "/@" + attrOne.Name;
                                                relationShip.Type = "2";
                                                if (!relationShipList.Contains(relationShip))
                                                {
                                                    relationShipList.Add(relationShip);
                                                }
                                            }
                                        }
                                        else
                                        {
                                            RelationShip relationShip = new RelationShip();
                                            relationShip.EvidenID = dataModelOne.ID;
                                            relationShip.ElmentID = dataModelTowe.ID;
                                            relationShip.XmlPath = optimizeSameNodeXML.XmlPath + "/@" + attrOne.Name;
                                            relationShip.Type = "2";
                                            if (!relationShipList.Contains(relationShip))
                                            {
                                                relationShipList.Add(relationShip);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception)
                    {
                    }
                }
            }
            return relationShipList;
        }
    }

    /// <summary>
    /// 对比实体
    /// </summary>
    public class RelationShip
    {

        /// <summary>
        /// 路径
        /// </summary>
        public string XmlPath { get; set; }

        /// <summary>
        /// 证据要素id
        /// </summary>
        public string EvidenID { get; set; }

        /// <summary>
        /// 要素ID
        /// </summary>
        public string ElmentID { get; set; }

        /// <summary>
        /// 证据名称ID
        /// </summary>
        public string EvidenNameID { get; set; }


        /// <summary>
        /// 类型1,比对成功 类型2比对失败
        /// </summary>
        public string Type { get; set; }

        /// <summary>
        /// 要素分类 1=分人员要素 2=待证事实
        /// </summary>
        public string ElementType { get; set; }

        /// <summary>
        /// 合并后要素ID
        /// </summary>
        public string MergerElementID { get; set; }
    }

    public static class Extensions
    {
        public static IEnumerable<T> Distinct<T>(
            this IEnumerable<T> source, Func<T, T, bool> comparer)
            where T : class
            => source.Distinct(new DynamicEqualityComparer<T>(comparer));

        private sealed class DynamicEqualityComparer<T> : IEqualityComparer<T>
            where T : class
        {
            private readonly Func<T, T, bool> _func;

            public DynamicEqualityComparer(Func<T, T, bool> func)
            {
                _func = func;
            }

            public bool Equals(T x, T y) => _func(x, y);

            public int GetHashCode(T obj) => 0;
        }
    }
}
